﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.Data.OleDb;
using System.Text.RegularExpressions;

namespace Our.Umbraco.uDbCompare
{
    public partial class MacroInUse : System.Web.UI.UserControl
    {
        public bool UseRemoteConnectionString { get; set; }

        private static string macroTemplateTag = "umbraco:macro";
        private static string macroContentTag = "UMBRACO_MACRO";

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
                BindData();
        }

        public void BindData()
        {
            if (SessionVars.IsValidDbConnection(UseRemoteConnectionString))
            {
                DataTable macroTable = Db.QueryDb("select macroAlias, macroname from cmsMacro", UseRemoteConnectionString);
                macroTable.DefaultView.Sort = "macroAlias asc";
                MacroDropDownList.DataTextField = "macroname";
                MacroDropDownList.DataValueField = "macroAlias";
                MacroDropDownList.DataSource = macroTable;
                MacroDropDownList.DataBind();

                SearchButton.Enabled = true;
                SearchAllButton.Enabled = true;
            }
        }


        private DataTable FindMacro(List<string> aliases)
        {
            string macroQuery = string.Format(@"select '{0}' as MacroLocation, c.nodeId, d.text as Name, cx.xml as Data 
	                                    from cmscontentxml cx 
	                                    join cmsContent c on cx.nodeid=c.nodeid 
	                                    join cmsDocument d on c.nodeid = d.nodeid 
	                                    where d.newest = 1
	                                     and [xml] like '%{1}%'
                                    union all
                                    select '{2}' as MacroLocation, nodeId, alias as Name, design as Data
                                    from cmsTemplate where design like '%{3}%'", 
                                    LinkItem.Content, macroContentTag, LinkItem.Template, macroTemplateTag);

            DataTable dt = Db.QueryDb(macroQuery, UseRemoteConnectionString);
            DataTable matchDt = dt.Clone();
            matchDt.Rows.Clear();
            matchDt.Columns.Add("Macro", typeof(string));

            foreach (string alias in aliases)
            {
                DataRow newRow = null;
                foreach (DataRow dr in dt.Rows)
                {
                    string macroLocationString = (string)dr["MacroLocation"];
                    LinkItem macroLocation = (LinkItem)Enum.Parse(typeof(LinkItem), macroLocationString);
                    string data = (string)dr["data"];

                    switch (macroLocation)
                    {
                        case LinkItem.Template:
                            // <\s*(?i)umbraco\:macro[^>]*>
                            // replace : with \: for regex
                            string regex = string.Format(@"<\s*(?i){0}[^>]*>", macroTemplateTag.Replace(":", @"\:"));

                            MatchCollection matches = Regex.Matches(data, regex);

                            foreach (Match match in matches)
                            {
                                // (?i)alias\s*=\s*["'][^"']*["']
                                string aliasRegex = string.Format(@"(?i)alias\s*=\s*[{0}']\s*{1}\s*[{0}']", "\"", alias);
                                Match aliasMatch = Regex.Match(match.Value, aliasRegex);
                                if (aliasMatch.Success)
                                {
                                    if (newRow == null)
                                        newRow = matchDt.NewRow();

                                    newRow["MacroLocation"] = macroLocation;
                                    newRow["Name"] = dr["Name"];
                                    newRow["Macro"] = alias;
                                    newRow["data"] += match.Value;
                                    newRow["nodeId"] = dr["nodeId"];
                                }
                            }
                            break;
                        case LinkItem.Content:
                            // <\?(?i)UMBRACO_MACRO\s*macroAlias\s*=\s*["'][^"']*["'][^>]*>
                            string umbRegex = string.Format(@"<\?(?i){1}\s*macroAlias\s*=\s*[{0}']\s*{2}\s*[{0}'][^>]*>", "\"", macroContentTag, alias);
                            Match umbMatch = Regex.Match(data, umbRegex);
                            if (umbMatch.Success)
                            {
                                if (newRow == null)
                                    newRow = matchDt.NewRow();

                                newRow["MacroLocation"] = macroLocation;
                                newRow["Name"] = dr["Name"];
                                newRow["Macro"] = alias;
                                newRow["data"] += umbMatch.Value;
                                newRow["nodeId"] = dr["nodeId"];
                            }
                            break;
                    }

                    if (newRow != null)
                    {
                        matchDt.Rows.Add(newRow);
                        newRow = null;
                    }
                }

            }

            return matchDt;
        }


        protected void SearchButton_OnClick(object sender, EventArgs e)
        {
            DataTable matchDt = FindMacro(new List<string>() {MacroDropDownList.SelectedValue});
            MacroGridView.DataSource = matchDt;
            MacroGridView.DataBind();

            NoResultsLabel.Visible = (matchDt.Rows.Count == 0);
        }

        protected void SearchAllButton_OnClick(object sender, EventArgs e)
        {
            var aliases = new List<string>();
            foreach (ListItem item in MacroDropDownList.Items)
            {
                aliases.Add(item.Value);
            }
            DataTable matchDt = FindMacro(aliases);

            var missing = new List<string>();
            foreach (var alias in aliases)
            {
                bool isMissing = true;
                foreach (DataRow row in matchDt.Rows)
                {
                    if (alias.CompareTo((string)row["Macro"]) == 0)
                        isMissing = false;
                }
                if (isMissing)
                {
                    var newRow = matchDt.NewRow();
                    newRow["MacroLocation"] = LinkItem.Unknown.ToString();
                    newRow["Name"] = string.Empty;
                    newRow["nodeId"] = -1;

                    newRow["Macro"] = alias;
                    newRow["data"] = "Missing";
                    matchDt.Rows.Add(newRow);
                }
            }
            MacroGridView.DataSource = matchDt;
            MacroGridView.DataBind();

            NoResultsLabel.Visible = (matchDt.Rows.Count == 0);
        }

        protected void MacroGridView_OnRowDataBound(object sender, GridViewRowEventArgs e)
        {
            if (e.Row.RowType == DataControlRowType.DataRow)
            {
                DataRowView drv = e.Row.DataItem as DataRowView;

                int nodeId = (int)drv["nodeId"];
                string macroLocationString = (string)drv["MacroLocation"];
                LinkItem macroLocation = (LinkItem)Enum.Parse(typeof(LinkItem), macroLocationString);

                if (macroLocation != LinkItem.Unknown)
                {
                    string url = uDbCompare.GetLinkUrl(macroLocation, nodeId, UseRemoteConnectionString);
                    uDbCompareUI.SetLinkCell(e.Row.Cells[1], nodeId.ToString(), url);
                }
            }
        }
    }
}